/**
 * 智能代码清理器
 * 自动剔除危险内容，保留安全的代码部分
 */

export interface SanitizeResult {
  sanitized: string
  isModified: boolean
  removedElements: string[]
  warnings: string[]
  info: string[]
}

export interface SanitizeOptions {
  removeScriptTags: boolean
  removeEventHandlers: boolean
  removeIframes: boolean
  removeObjects: boolean
  preserveComments: boolean
  logChanges: boolean
}

const DEFAULT_OPTIONS: SanitizeOptions = {
  removeScriptTags: false, // 默认不移除script标签，因为它们可能是正常代码
  removeEventHandlers: true, // 移除内联事件处理器
  removeIframes: true, // 移除iframe（除非明确需要）
  removeObjects: true, // 移除object/embed标签
  preserveComments: true, // 保留注释
  logChanges: true // 记录更改
}

/**
 * 智能清理代码片段
 */
export function sanitizeCodeSnippet(code: string, options: Partial<SanitizeOptions> = {}): SanitizeResult {
  const opts = { ...DEFAULT_OPTIONS, ...options }
  const result: SanitizeResult = {
    sanitized: code || '',
    isModified: false,
    removedElements: [],
    warnings: [],
    info: []
  }

  if (!code) {
    return result
  }

  let sanitized = code

  // 1. 移除明确危险的JavaScript协议
  sanitized = removeDangerousProtocols(sanitized, result, opts)

  // 2. 移除或清理内联事件处理器
  if (opts.removeEventHandlers) {
    sanitized = removeInlineEventHandlers(sanitized, result, opts)
  }

  // 3. 处理可能危险的script标签
  sanitized = processScriptTags(sanitized, result, opts)

  // 4. 处理iframe标签
  if (opts.removeIframes) {
    sanitized = processIframeTags(sanitized, result, opts)
  }

  // 5. 移除object/embed标签
  if (opts.removeObjects) {
    sanitized = removeObjectTags(sanitized, result, opts)
  }

  // 6. 清理其他潜在危险内容
  sanitized = cleanupMiscellaneous(sanitized, result, opts)

  // 7. 标准化格式
  sanitized = normalizeWhitespace(sanitized)

  result.sanitized = sanitized
  return result
}

/**
 * 移除危险的协议链接
 */
function removeDangerousProtocols(code: string, result: SanitizeResult, opts: SanitizeOptions): string {
  const protocolPatterns = [
    { pattern: /javascript:\s*[^"'\s][^"']*(?=["'\s>]|$)/gi, name: 'JavaScript协议' },
    { pattern: /vbscript:\s*[^"'\s][^"']*(?=["'\s>]|$)/gi, name: 'VBScript协议' },
    { pattern: /data:\s*text\/html[^"']*(?=["'\s>]|$)/gi, name: 'Data URI HTML' }
  ]

  let sanitized = code
  protocolPatterns.forEach(({ pattern, name }) => {
    const matches = code.match(pattern)
    if (matches) {
      sanitized = sanitized.replace(pattern, match => {
        result.removedElements.push(`${name}: ${match.substring(0, 50)}...`)
        result.isModified = true
        return opts.preserveComments ? `/* 已移除危险内容: ${name} */` : ''
      })
      result.warnings.push(`移除了 ${matches.length} 个${name}引用`)
    }
  })

  return sanitized
}

/**
 * 移除内联事件处理器
 */
function removeInlineEventHandlers(code: string, result: SanitizeResult, opts: SanitizeOptions): string {
  // 匹配 onclick、onmouseover 等事件处理器
  const eventPattern = /\s+on\w+\s*=\s*["'][^"']*["']/gi
  const matches = code.match(eventPattern)

  if (matches) {
    let sanitized = code.replace(eventPattern, match => {
      result.removedElements.push(`事件处理器: ${match.trim()}`)
      result.isModified = true
      return opts.preserveComments ? ` /* 已移除: ${match.trim()} */` : ''
    })

    result.warnings.push(`移除了 ${matches.length} 个内联事件处理器`)
    return sanitized
  }

  return code
}

/**
 * 智能处理script标签
 */
function processScriptTags(code: string, result: SanitizeResult, opts: SanitizeOptions): string {
  // 检查是否包含完整的script标签
  const scriptTagPattern = /<script[^>]*>[\s\S]*?<\/script>/gi
  const scriptTags = code.match(scriptTagPattern)

  if (!scriptTags) {
    return code
  }

  let sanitized = code

  scriptTags.forEach(scriptTag => {
    const isSimpleReference = isSimpleScriptReference(scriptTag)
    const containsDangerousCode = containsHighRiskCode(scriptTag)

    if (containsDangerousCode) {
      // 包含危险代码，完全移除
      sanitized = sanitized.replace(scriptTag, opts.preserveComments ? '<!-- 已移除包含危险代码的script标签 -->' : '')
      result.removedElements.push(`危险Script: ${scriptTag.substring(0, 100)}...`)
      result.warnings.push('移除了包含危险代码的script标签')
      result.isModified = true
    } else if (isSimpleReference) {
      // 简单的外部脚本引用，保留但记录
      result.info.push(`保留外部脚本引用: ${extractScriptSrc(scriptTag)}`)
    } else if (opts.removeScriptTags) {
      // 根据选项决定是否移除
      sanitized = sanitized.replace(scriptTag, opts.preserveComments ? '<!-- 已移除script标签内容 -->' : '')
      result.removedElements.push(`Script内容: ${scriptTag.substring(0, 100)}...`)
      result.warnings.push('移除了script标签内容')
      result.isModified = true
    } else {
      // 保留但记录
      result.info.push('保留了script标签内容（已确认安全）')
    }
  })

  return sanitized
}

/**
 * 判断是否为简单的脚本引用
 */
function isSimpleScriptReference(scriptTag: string): boolean {
  // 检查是否只是简单的外部脚本引用
  const srcMatch = scriptTag.match(/src\s*=\s*["']([^"']+)["']/i)
  const hasInnerContent = /<script[^>]*>([\s\S]*?)<\/script>/i.test(scriptTag)

  return !!(srcMatch && (!hasInnerContent || scriptTag.match(/<script[^>]*>\s*<\/script>/i)))
}

/**
 * 检查是否包含高风险代码
 */
function containsHighRiskCode(scriptTag: string): boolean {
  const dangerousPatterns = [
    /eval\s*\(/i,
    /document\.write\s*\(/i,
    /innerHTML\s*=/i,
    /outerHTML\s*=/i,
    /execScript\s*\(/i,
    /setTimeout\s*\(\s*["'][^"']*["']/i, // 字符串形式的setTimeout
    /setInterval\s*\(\s*["'][^"']*["']/i, // 字符串形式的setInterval
    /Function\s*\(\s*["'][^"']*["']/i, // 动态函数创建
    /window\[\s*["'][^"']*["']\s*\]/i // 动态属性访问
  ]

  return dangerousPatterns.some(pattern => pattern.test(scriptTag))
}

/**
 * 提取script的src属性
 */
function extractScriptSrc(scriptTag: string): string {
  const match = scriptTag.match(/src\s*=\s*["']([^"']+)["']/i)
  return match ? match[1] : '未知'
}

/**
 * 处理iframe标签
 */
function processIframeTags(code: string, result: SanitizeResult, opts: SanitizeOptions): string {
  const iframePattern = /<iframe[^>]*(?:\/>|>[\s\S]*?<\/iframe>)/gi
  const matches = code.match(iframePattern)

  if (matches) {
    let sanitized = code.replace(iframePattern, match => {
      // 检查是否为安全的iframe
      if (isSafeIframe(match)) {
        result.info.push(`保留安全的iframe: ${extractIframeSrc(match)}`)
        return match
      } else {
        result.removedElements.push(`Iframe: ${match.substring(0, 100)}...`)
        result.isModified = true
        return opts.preserveComments ? '<!-- 已移除iframe标签 -->' : ''
      }
    })

    const removedCount = result.removedElements.filter(e => e.startsWith('Iframe:')).length
    if (removedCount > 0) {
      result.warnings.push(`移除了 ${removedCount} 个iframe标签`)
    }
    return sanitized
  }

  return code
}

/**
 * 判断iframe是否安全
 */
function isSafeIframe(iframe: string): boolean {
  // 检查是否包含srcdoc或危险属性
  const dangerousAttributes = [/srcdoc\s*=/i, /javascript:/i, /data:\s*text\/html/i]

  return !dangerousAttributes.some(pattern => pattern.test(iframe))
}

/**
 * 提取iframe的src属性
 */
function extractIframeSrc(iframe: string): string {
  const match = iframe.match(/src\s*=\s*["']([^"']+)["']/i)
  return match ? match[1] : '内嵌内容'
}

/**
 * 移除object/embed标签
 */
function removeObjectTags(code: string, result: SanitizeResult, opts: SanitizeOptions): string {
  const patterns = [
    { pattern: /<object[^>]*(?:\/>|>[\s\S]*?<\/object>)/gi, name: 'Object' },
    { pattern: /<embed[^>]*\/?>/gi, name: 'Embed' }
  ]

  let sanitized = code
  patterns.forEach(({ pattern, name }) => {
    const matches = code.match(pattern)
    if (matches) {
      sanitized = sanitized.replace(pattern, match => {
        result.removedElements.push(`${name}: ${match.substring(0, 100)}...`)
        result.isModified = true
        return opts.preserveComments ? `<!-- 已移除${name}标签 -->` : ''
      })
      result.warnings.push(`移除了 ${matches.length} 个${name}标签`)
    }
  })

  return sanitized
}

/**
 * 清理其他杂项危险内容
 */
function cleanupMiscellaneous(code: string, result: SanitizeResult, opts: SanitizeOptions): string {
  let sanitized = code

  // 移除form标签（可能用于钓鱼）
  const formPattern = /<form[^>]*>[\s\S]*?<\/form>/gi
  const forms = sanitized.match(formPattern)
  if (forms) {
    sanitized = sanitized.replace(formPattern, match => {
      result.removedElements.push(`Form: ${match.substring(0, 100)}...`)
      result.isModified = true
      return opts.preserveComments ? '<!-- 已移除form标签 -->' : ''
    })
    result.warnings.push(`移除了 ${forms.length} 个form标签`)
  }

  // 清理null字符和控制字符
  const controlChars = sanitized.match(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g)
  if (controlChars) {
    sanitized = sanitized.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '')
    result.info.push(`清理了 ${controlChars.length} 个控制字符`)
    result.isModified = true
  }

  return sanitized
}

/**
 * 标准化空白字符
 */
function normalizeWhitespace(code: string): string {
  return code
    .replace(/\r\n/g, '\n') // 统一换行符
    .replace(/\r/g, '\n')
    .replace(/\t/g, '  ') // 将tab转换为空格
    .replace(/[ \t]+$/gm, '') // 移除行尾空白
    .replace(/\n{3,}/g, '\n\n') // 限制连续空行
}

/**
 * 预设的清理策略
 */
export const SANITIZE_PRESETS = {
  // 严格模式：移除所有可能的危险内容
  STRICT: {
    removeScriptTags: true,
    removeEventHandlers: true,
    removeIframes: true,
    removeObjects: true,
    preserveComments: true,
    logChanges: true
  },

  // 温和模式：只移除明确危险的内容
  MODERATE: {
    removeScriptTags: false,
    removeEventHandlers: true,
    removeIframes: false,
    removeObjects: true,
    preserveComments: true,
    logChanges: true
  },

  // 宽松模式：主要用于代码展示
  PERMISSIVE: {
    removeScriptTags: false,
    removeEventHandlers: false,
    removeIframes: false,
    removeObjects: false,
    preserveComments: true,
    logChanges: true
  }
} as const
